﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
//using System.Xml.XPath;

namespace SQL_Manager
{
    public struct Profile
    {
        //
        // Unique identifier
        //
        public int id;
        //
        // Profile name, not database
        //
        public string name;
        //
        // Profile category, to provide support for organization
        //
        public string category;
        //
        // Server credentials
        //
        public string username;
        public string password;
        public string hostname;
        public string database;
        //
        // The driver type to use when connecting to the database [MySQL, PGSQL, SQLite]
        //
        public DriverType driver;
    }

    public static class ApplicationProfiles
    {
        //
        // Used to store the profiles, the accessor/mutator 'profiles' uses this
        //
        static private ArrayList _profiles = null;
        static private XmlDocument profileData = null;

        //
        // Populates _profiles with profile data from the Profile storage
        //
        static public void loadProfiles()
        {
            try
            {
                _profiles = new ArrayList();
                profileData = new XmlDocument();
                profileData.Load("../../Storage/Profiles.xml");

                foreach (XmlNode node in profileData.ChildNodes[1])
                {
                    _profiles.Add(new Profile
                    {
                        id = _profiles.Count,
                        name = node.Attributes[0].Value,
                        category = node.Attributes[1].Value,
                        username = node.ChildNodes[0].Attributes[0].Value,
                        password = node.ChildNodes[1].Attributes[0].Value,
                        database = node.ChildNodes[2].Attributes[0].Value,
                        hostname = node.ChildNodes[3].Attributes[0].Value,
                        driver = (DriverType)(int.Parse(node.ChildNodes[4].Attributes[0].Value))
                    });
                }
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                try
                {
                    System.IO.Directory.CreateDirectory("../../Storage/");

                    XmlTextWriter writer = new XmlTextWriter("../../Storage/Profiles.xml", Encoding.UTF8);
                    writer.Formatting = Formatting.Indented;

                    writer.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
                    writer.WriteStartElement("Profiles");
                    writer.WriteEndElement();

                    writer.Close();
                }
                catch { }
            }
            catch (System.IO.FileNotFoundException)
            {
                try
                {
                    XmlTextWriter writer = new XmlTextWriter("../../Storage/Profiles.xml", Encoding.UTF8);
                    writer.Formatting = Formatting.Indented;

                    writer.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
                    writer.WriteStartElement("Profiles");
                    writer.WriteEndElement();

                    writer.Close();
                }
                catch { }
            }
            catch (System.Security.SecurityException)
            {
                //TODO: Send a security message to the interface
            }
            catch { }
        }

        static public void updateProfile(Profile profile)
        {
            //
            // Update all the data, even if it's unchanged.
            //
            // Attributes
            profileData.ChildNodes[1].ChildNodes[profile.id].Attributes[0].Value = profile.name;
            profileData.ChildNodes[1].ChildNodes[profile.id].Attributes[1].Value = profile.category;
            // Elements
            profileData.ChildNodes[1].ChildNodes[profile.id].ChildNodes[0].Attributes[0].Value = profile.username;
            profileData.ChildNodes[1].ChildNodes[profile.id].ChildNodes[1].Attributes[0].Value = profile.password;
            profileData.ChildNodes[1].ChildNodes[profile.id].ChildNodes[2].Attributes[0].Value = profile.database;
            profileData.ChildNodes[1].ChildNodes[profile.id].ChildNodes[3].Attributes[0].Value = profile.hostname;
            profileData.ChildNodes[1].ChildNodes[profile.id].ChildNodes[4].Attributes[0].Value = (int)profile.driver + "";

            // Save
            _profiles[profile.id] = profile;
            profileData.Save("../../Storage/Profiles.xml");
        }

        static public void removeProfile(Profile profile)
        {
            profileData.ChildNodes[1].RemoveChild(profileData.ChildNodes[1].ChildNodes[profile.id]);
            _profiles.RemoveAt(profile.id);
            profileData.Save("../../Storage/Profiles.xml");
            loadProfiles();
        }

        static public void insertProfile(Profile profile)
        {
            //
            // Assign it a fresh ID
            //
            profile.id = _profiles.Count;
            _profiles.Add(profile);

            //
            // Form the new element
            //
            XmlNode newNode = profileData.CreateNode("element", "Profile", "");
            // Attributes
            newNode.Attributes.Append(profileData.CreateAttribute("name"));
            newNode.Attributes.Append(profileData.CreateAttribute("category"));
            // Elements
            newNode.AppendChild(profileData.CreateElement("Username"));
            newNode.ChildNodes[0].Attributes.Append(profileData.CreateAttribute("value"));
            newNode.AppendChild(profileData.CreateElement("Password"));
            newNode.ChildNodes[1].Attributes.Append(profileData.CreateAttribute("value"));
            newNode.AppendChild(profileData.CreateElement("Database"));
            newNode.ChildNodes[2].Attributes.Append(profileData.CreateAttribute("value"));
            newNode.AppendChild(profileData.CreateElement("Hostname"));
            newNode.ChildNodes[3].Attributes.Append(profileData.CreateAttribute("value"));
            newNode.AppendChild(profileData.CreateElement("DriverType"));
            newNode.ChildNodes[4].Attributes.Append(profileData.CreateAttribute("value"));

            //
            // Add the data to corresponding attributes and elements
            //
            // Attributes
            newNode.Attributes[0].Value = profile.name;
            newNode.Attributes[1].Value = profile.category;
            // Elements
            newNode.ChildNodes[0].Attributes[0].Value = profile.username;
            newNode.ChildNodes[1].Attributes[0].Value = profile.password;
            newNode.ChildNodes[2].Attributes[0].Value = profile.database;
            newNode.ChildNodes[3].Attributes[0].Value = profile.hostname;
            newNode.ChildNodes[4].Attributes[0].Value = (int)profile.driver + "";

            //
            // Append node and save progress
            //
            profileData.ChildNodes[1].AppendChild(newNode);
            profileData.Save("../../Storage/Profiles.xml");
        }

        //
        // Ensures that _profiles is always up-to-date
        //
        static public ArrayList profiles
        {
            get
            {
                if (_profiles == null)
                {
                    loadProfiles();
                }
                
                return _profiles;
            }
            set
            {
                _profiles = value;
            }
        }
    }
}
